package com.googlecode.recycled.xml;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.googlecode.recycled.lang.assertions.Assert;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;

import java.util.List;

public class Nodes {

    protected Nodes() {
    }

    public static void setText(Node node, String text) {
        Assert.notNull(text);
        Node textNode = Assert.notNull(node).getFirstChild();
        if (textNode == null) {
            textNode = node.getOwnerDocument().createTextNode(text);
            node.appendChild(textNode);
        } else {
            textNode.setNodeValue(text);
        }
    }

    public static void addNode(Node parent, Node child) {
        Assert.notNull(child);
        Document parentDocument = Assert.notNull(parent).getOwnerDocument();
        if (parentDocument == null) {
            parentDocument = (Document) parent;
        }
        if (!parentDocument.equals(child.getOwnerDocument())) {
            child = parentDocument.importNode(child, true);
        }
        parent.appendChild(child);
    }

    public static List<Node> asList(NodeIterator nodeIterator) {
        List<Node> nodes = Lists.newLinkedList();
        Node node;
        while ((node = nodeIterator.nextNode()) != null) {
            nodes.add(node);
        }
        return nodes;
    }

    public static List<Element> asElements(NodeIterator nodeIterator) {
        return Lists.newLinkedList(Iterables.transform(asList(nodeIterator), new NodeToElementFunction()));
    }

    public static List<Node> asList(NodeList nodeList) {
        List<Node> nodes = Lists.newArrayListWithExpectedSize(nodeList.getLength());
        for (int i = 0; i < nodeList.getLength(); i++) {
            nodes.add(nodeList.item(i));
        }
        return nodes;
    }

    public static List<Element> asElements(NodeList nodeList) {
        return Lists.newLinkedList(Iterables.transform(asList(nodeList), new NodeToElementFunction()));
    }

    public static class NodeToTextFunction implements Function<Node, String> {

        @Override
        public String apply(Node from) {
            return from.getTextContent();
        }

    }

    public static class NodeToElementFunction implements Function<Node, Element> {

        @Override
        public Element apply(Node from) {
            return (Element) from;
        }

    }

    public static boolean isAttribute(Node node) {
        return Assert.notNull(node).getNodeType() == Node.ATTRIBUTE_NODE;
    }

}
